/*
 *  Texture.cpp
 *  Ray Tracing
 *
 *  Created by Jean-Marc Comby + Romain Dequesne on Tue Jun 08 2004.
 *  Copyright (c) 2004. All rights reserved.
 *
 */

#include "Texture.hpp"

#include "Formes/Forme.hpp"

#include "Image/ReadImageFile.hpp"

#include <iostream>

using namespace std;

/**
 * Constructeur standard. On initialise tous les champs de Materiau
 * (aucun bruit n'est appliqué).
 *
 * Lance une exception du type Erreur si le type d'image est
 * incorrect.
 *
 * @param refl coefficient de réflexion.
 * @param trans coefficient de transparence.
 * @param indice indice de réfraction.
 * @param reg coefficient de diffusion.
 * @param name nom du fichier de l'image à charger.
 * @param c pointeur sur la Forme à mapper.
 * @param larg fréquence de répétition de l'image.
 */
Texture::Texture(const double& refl, const double& trans,
		 const double& indice, const double& reg,
		 const string& name, const Forme *c, const unsigned int& larg)
  : Materiau( refl, trans, indice, reg ), Volume( c ), Frequence( larg )
{
  if ( name != "" )
    {
      cout << "Importation de la texture depuis " << name << endl;
      ComposantCouleur *image;
      size_t locJpg( name.find(".jpg") ), locJpeg( name.find(".jpeg") ),
	locPng( name.find(".png") );
      if ( locJpg != string::npos )
	image = litJpeg(name.c_str(), Hauteur, Largeur);
      else if ( locJpeg != string::npos )
	image = litJpeg(name.c_str(), Hauteur, Largeur);
      else if ( locPng  != string::npos )
	image = litpng(name.c_str(), Hauteur, Largeur);
      else
	throw Erreur( false, 0, "Format Image de texture invalide " + name,
		      "Texture" );

      aMapper = convertImage( image, Hauteur, Largeur );
    }

  Type = tTexture;
}

/**
 * Constructeur standard. On initialise tous les champs de Materiau
 * (aucun bruit n'est appliqué).
 *
 * Lance une exception du type Erreur si le type d'image est
 * incorrect.
 *
 * @param refl coefficient de réflexion.
 * @param trans coefficient de transparence.
 * @param indice indice de réfraction.
 * @param reg coefficient de diffusion.
 * @param bruit coefficient de bruit.
 * @param name nom du fichier de l'image à charger.
 * @param c pointeur sur la Forme à mapper.
 * @param larg fréquence de répétition de l'image.
 */
Texture::Texture(const double& refl, const double& trans,
		 const double& indice, const double& reg, const double& bruit,
		 const string& name, const Forme *c, const unsigned int& larg)
  : Materiau( refl, trans, indice, reg, bruit ), Volume( c ), Frequence( larg )
{
  ComposantCouleur *image;
  size_t locJpg( name.find(".jpg") ), locJpeg( name.find(".jpeg") ),
    locPng( name.find(".png") );
  if ( locJpg != string::npos )
    image = litJpeg( name.c_str(), Hauteur, Largeur );
  else if ( locJpeg != string::npos )
    image = litJpeg( name.c_str(), Hauteur, Largeur );
  else if ( locPng  != string::npos )
    image = litpng( name.c_str(), Hauteur, Largeur );
  else
    throw Erreur( false, 0, "Format Image de texture invalide " + name,
		  "Texture" );

  aMapper = convertImage( image, Hauteur, Largeur );

  Type = tTexture;
}

/**
 * Le destructeur n'a rien de spécial à faire.
 */
Texture::~Texture()
{}

/**
 * Permet de modifier la Forme à mapper.
 *
 * @param obj nouvelle valeur du pointeur Volume.
 */
void Texture::setVolume( const Forme* obj )
{
  Volume = obj;
}

/**
 * Permet la Couleur de lire dans l'image à mapper. La méthode
 * spécifique à Forme est appelée pour obtenir les coordonnées du
 * point pt dans la carte intrinsèque à la surface.
 *
 * @param pt point dont on veut connaître la Couleur.
 * @return une référence constante sur la valeur de la Couleur du
 * point voulu.
 */
const Couleur& Texture::mappingObject(const Coord& pt)
{
  int i,j; // coord des pixels sur l image
  Volume -> mapping( pt, i, j, Frequence, Hauteur, Largeur );
  return aMapper.pixel( j , i );
}

/**
 * Méthode générique permettant de récupérer la Couleur du Materiau
 * pour le point donné.
 *
 * @param intersection coordonnées du point d'intersection de la Forme
 * et du Rayon.
 * @return une référence constante sur Color, qui est modifiée par un
 * appel à mappingObject.
 */
Couleur Texture::couleur(const Coord& intersection)
{
  return mappingObject( intersection );
}
